package decorator

//////////////////////////////////
type Beverage interface {
	GetDescription() string
	Cost() int
}

type CondimentDecorator interface {
	GetDescription() string
	Cost() int
}

//////////////////////////////////
type HouseBlend struct {
}

func (d *HouseBlend) Cost() int {
	return 1
}

func (d *HouseBlend) GetDescription() string {
	return "HouseBlend"
}

type DarkRoast struct {
}

func (d *DarkRoast) Cost() int {
	return 2
}

func (d *DarkRoast) GetDescription() string {
	return "DarkRoast"
}

type Espresso struct {
}

func (d *Espresso) Cost() int {
	return 3
}

func (d *Espresso) GetDescription() string {
	return "Espresso"
}

type Decaf struct {
}

func (d *Decaf) Cost() int {
	return 4
}

func (d *Decaf) GetDescription() string {
	return "Decaf"
}

///////////////////////////////////
type Milk struct {
	beverage Beverage
}

func NewMilk(b Beverage) *Milk {
	r := new(Milk)
	r.beverage = b

	return r
}

func (d *Milk) Cost() int {
	return d.beverage.Cost() + 1
}

func (d *Milk) GetDescription() string {
	return d.beverage.GetDescription() + ",Milk"
}

type Mocha struct {
	beverage Beverage
}

func NewMocha(b Beverage) *Mocha {
	r := new(Mocha)
	r.beverage = b

	return r
}

func (d *Mocha) Cost() int {
	return d.beverage.Cost() + 2
}

func (d *Mocha) GetDescription() string {
	return d.beverage.GetDescription() + ",Mocha"
}

type Soy struct {
	beverage Beverage
}

func NewSoy(b Beverage) *Soy {
	r := new(Soy)
	r.beverage = b

	return r
}

func (d *Soy) Cost() int {
	return d.beverage.Cost() + 3
}

func (d *Soy) GetDescription() string {
	return d.beverage.GetDescription() + ",Soy"
}

type Whip struct {
	beverage Beverage
}

func NewWhip(b Beverage) *Whip {
	r := new(Whip)
	r.beverage = b

	return r
}

func (d *Whip) Cost() int {
	return d.beverage.Cost() + 4
}

func (d *Whip) GetDecription() string {
	return d.beverage.GetDescription() + ",Whip"
}
